package com.tinem.platform.web.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.tinem.platform.module.pojo.co.GatewayHeadName;
import com.tinem.platform.module.pojo.co.RedisKeyEnum;
import com.tinem.platform.module.pojo.enums.security.SignatureAlgorithm;
import com.tinem.platform.module.pojo.vo.error.UserException;
import com.tinem.platform.module.starter.sdk.MessageCode;
import com.tinem.platform.web.gateway.util.GatewayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author fengzhihao
 * @version v1
 * @program: platform
 * @className ChannelScopeGatewayFilterFactory
 * @description 客户端请求签名
 * @site 
 * @company 
 * @create 2020-07-03 12:26
 */
@Slf4j
@Component
public class ClientReqSignGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            String client = GatewayUtil.getClient(exchange);
            String clientRedisKey = RedisKeyEnum.client_info.getKey(client);

            if(!Boolean.parseBoolean((String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqSign"))){
                //不做请求签名
                return chain.filter(exchange);
            }
            // 缓存中请求签名类型
            String  redisReqSignType = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqSignType");
            // 客户端上传请求签名类型
            String  clientReqSignType = exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_SIGN_TYPE);
            if(!StrUtil.equals(redisReqSignType,clientReqSignType)){
                // 请求签名类型不匹配
                throw new UserException(MessageCode.ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SIGN_TYPE,redisReqSignType,clientReqSignType);
            }

            String requestBody = exchange.getAttribute(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_BODY);
            String reqSignKey = (String) stringRedisTemplate.opsForHash().get(clientRedisKey, "reqSignKey");
            // 客户端上传请求签名
            String clientReqSign = GatewayUtil.getClientReqSign(exchange);
            String apiRequestId = GatewayUtil.getApiReq(exchange);
            if(!SignatureAlgorithm.valueOf(redisReqSignType).verify(requestBody,reqSignKey,GatewayUtil.getReqTimestamp(exchange),apiRequestId,clientReqSign)){
                // 请求签名验证失败
                throw new UserException(MessageCode.ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SIGN);
            }
            return chain.filter(exchange);
        };
    }
}
